const assert = require('assert')
const floodController = require('../../ddos/controller')
const FloodAgent = require('../../ddos/agent')
const FloodListener = require('../../ddos/listener')

const AGENT_IP = '127.0.0.1'
const TARGET_IP = '127.0.0.1'

describe('FloodController Interface Static Test', function () {
  let controller

  before(function () {
    // runs before all tests in this block
    assert.ok(floodController)
    assert.ok(floodController.init)
    assert.ok(floodController.addAgent)
    assert.ok(floodController.removeAgent)
    assert.ok(floodController.getAgents)
    assert.ok(floodController.findAgent)
    assert.ok(floodController.startFlood)
    assert.ok(floodController.stopFlood)
    assert.ok(floodController.getState)
    assert.ok(floodController.getTrafficStat)
  })

  after(function () {
    // runs after all tests in this block
  })

  it('controller should set correct internal data  after init ', function () {
    floodController.init()
    let listener = new FloodListener(8000, floodController)
    listener.start()

    let state = floodController.getState()
    assert.equal('idle', state.state)
    let agents = floodController.getAgents()
    assert.equal(0, agents.length)

    let data = floodController.getState()
  })

  it(' agent list should have more elements when addAgent invoked', function () {
    floodController.addAgent(new FloodAgent(AGENT_IP))
    let agents = floodController.getAgents()
    assert.equal(1, agents.length)
  })

  it(' controller should find agent when given ip', function () {
    let selector = {host: AGENT_IP}
    let agent = floodController.findAgent(selector)
    assert.ok(agent)
  })

  it(' agent should be in started state when startFlood ', function () {
    assert.doesNotThrow(
      () => {
        floodController.startFlood(TARGET_IP, {type: 'icmp'})
      }
    )
    let state = floodController.getState()
    assert.equal('started', state.state)
  })

  it(' controller should reject  state when already startFlood ', function () {
    assert.throws(
      () => {
        floodController.startFlood(TARGET_IP, {type: 'icmp'})
      }
    )
  })

  it(' traffic stat should change  when get every 2 secnonds ', function (done) {
    setTimeout(() => {
      let trafficInfo = floodController.getTrafficStat()
      console.log('trafficInfo %o', trafficInfo)
      assert.ok(trafficInfo.packetSent > 1000)
      assert.ok(trafficInfo.byteSent > 1000)
      done()
    }, 1000)
  })

  it(' agent should be in idle state when stopFood', function () {
    assert.doesNotThrow(
      () => {
        floodController.stopFlood()
      }
    )
  })

  it(' controller should reject stopFlood when flood not started ', function () {
    assert.throws(
      () => {
        floodController.stopFlood()
      }
    )
  })

  it(' agent list should remove specific element when removeAgent invoked', function () {
    let cond = {host: AGENT_IP}
    let agent = floodController.findAgent(cond)
    assert.ok(agent)
    let ret = floodController.removeAgent(agent)
    assert.equal(0, ret)
  })

  it(' controller should reject when ip_addr is not valid ', () => {
    let ip = '127.0.0.999'
    assert.throws(() => { floodController.startFlood(ip, {}) })
  })

  it(' controller should work when ip_addr is  valid ', () => {
    let ip = '127.0.0.1'
    assert.doesNotThrow(() => { floodController.startFlood(ip, {}) })
  })
})
